package hos.java.util;

import java.io.File;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;


public final class CrashUtils {

    private static final String FILE_SEP = System.getProperty("file.separator");

    private static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER =
            Thread.getDefaultUncaughtExceptionHandler();

    private CrashUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    /**
     * Initialization
     *
     * @param crashDir        The directory of saving crash information.
     * @param onCrashListener The crash listener.
     */
    public static void init(final File crashDir, final OnCrashListener onCrashListener) {
        init(crashDir.getAbsolutePath(), onCrashListener);
    }

    /**
     * Initialization
     *
     * @param crashDirPath    The directory's path of saving crash information.
     * @param onCrashListener The crash listener.
     */
    public static void init(final String crashDirPath, final OnCrashListener onCrashListener) {
        String dirPath = crashDirPath.endsWith(FILE_SEP) ? crashDirPath : crashDirPath + FILE_SEP;
        Thread.setDefaultUncaughtExceptionHandler(
                getUncaughtExceptionHandler(dirPath, onCrashListener));
    }

    public static void print(final Throwable e) {
        UncaughtExceptionHandler exceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        if (exceptionHandler != null) {
            exceptionHandler.uncaughtException(Thread.currentThread(), e);
        }
    }

    /**
     * 将数据拼接成字符串
     *
     * @param contents 内容
     * @return
     */
    public static String processBody(final Object... contents) {
        String body = "Log with null object.";
        if (contents != null) {
            if (contents.length == 1) {
                Object object = contents[0];
                body = object == null ? "null" : object.toString();
            } else {
                String line = System.getProperty("line.separator");
                StringBuilder sb = new StringBuilder();
                for (int i = 0, len = contents.length; i < len; ++i) {
                    Object content = contents[i];
                    sb.append("args")
                            .append("[")
                            .append(i)
                            .append("]")
                            .append(" = ")
                            .append(content == null ? "null" : content.toString())
                            .append(line);
                }
                body = sb.toString();
            }
        }
        return body;
    }

    private static UncaughtExceptionHandler getUncaughtExceptionHandler(final String dirPath,
                                                                        final OnCrashListener onCrashListener) {
        return new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(final Thread t, final Throwable e) {
                @SuppressWarnings("SimpleDateFormat") final String time = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss").format(new Date());
                final String info = ThrowableUtils.getFullStackTrace(e);
                final String crashFile = dirPath + time + "_crash.log";
                if (onCrashListener != null) {
                    onCrashListener.onCrash(crashFile, time, info);
                }
                if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null) {
                    DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(t, e);
                }
            }
        };
    }

    ///////////////////////////////////////////////////////////////////////////
    // interface
    ///////////////////////////////////////////////////////////////////////////

    public interface OnCrashListener {
        void onCrash(String crashFile, String time, String info);
    }

}
